module service.ApplyService;

import repository;
import model;
import client.MsgServerClient;
import msgtrans;
import hunt.logging;
import message.Constants;
import message.MsgDefine;
import std.conv : to;
import core.stdc.time;
import google.protobuf;
import std.array;

class ApplyService {

    static void dealApplyContancsReq(ApplyContact req)
    {
        FriendApply friendApply = new FriendApply;
        TransportSession msgClient = null;
        friendApply.userId = to!int(req.fromId);
        friendApply.friendId = to!int(req.toId);
        friendApply.status = 0;
        friendApply.message = req.message;
        friendApply.created = core.stdc.time.time(null);
        friendApply.src = req.src;

        auto friendApplyRepo = new FriendApplyRepository;
        auto friendRepo = new FriendRepository;
        Friend selfPeer = friendRepo.findByUid(to!int(req.fromId), to!int(req.toId));
        Friend friendPeer = friendRepo.findByUid(to!int(req.toId), to!int(req.fromId));

        if(selfPeer !is null && friendPeer !is null) //已经是好友了
        {
            logError("already friend");
        }

        if(selfPeer is null && friendPeer is null) //彼此互删了或者第一次添加好友
        {
            FriendApply f = friendApplyRepo.findApply(friendApply);
            if (f is null)
            {
                // 生成 chatId
                int id = friendApplyRepo.putApplyContactReq(friendApply);
                req.chatId = to!string(id);
            }
            else
            {
                req.chatId = to!string(f.id);
                friendApplyRepo.updateAll(req.chatId,req.message,cast(int)req.src, 0);
            }

            msgClient = MsgServerClient.getInstance().getForwardClient(to!int(req.toId));
            msgClient.send(new MessageBuffer(MESSAGE.CMD_APPLY_FRIEND_REQ,req.toProtobuf.array));
        }
        else if(selfPeer !is null) // toId 把 fromId 删了
        {
            req.chatId = to!string(selfPeer.chatId);
            friendApplyRepo.updateAll(req.chatId,req.message,cast(int)req.src, 0);
            msgClient = MsgServerClient.getInstance().getForwardClient(to!int(req.toId));
            msgClient.send(new MessageBuffer(MESSAGE.CMD_APPLY_FRIEND_REQ,req.toProtobuf.array));
        }
        else // fromId 把 toId 删除了
        {
            req.chatId = to!string(friendPeer.chatId);
            friendRepo.putSingle(req.fromId,req.toId,req.chatId,req.src);
            friendApplyRepo.updateAll(req.chatId,req.message,cast(int)req.src, 1);

            auto users = ApplyService.getUsers([req.fromId,req.toId],req.fromId);
            auto addFriend = new AddContact;
            addFriend.chatId = req.chatId;
            if (users !is null || users.length == 2) // 向好友双方发送回调信息
            {
                msgClient = MsgServerClient.getInstance().getForwardClient(to!int(users[1].id));
                addFriend.user = users[0];
                addFriend.toId = users[1].id;
                msgClient.send(new MessageBuffer(MESSAGE.CMD_DEAL_FRIEND_RES,addFriend.toProtobuf.array));

                msgClient = MsgServerClient.getInstance().getForwardClient(to!int(users[0].id));
                addFriend.user = users[1];
                addFriend.toId = users[0].id;
                msgClient.send(new MessageBuffer(MESSAGE.CMD_DEAL_FRIEND_RES,addFriend.toProtobuf.array));
            }

            ChatMapAction chatMapAction = new ChatMapAction;
            chatMapAction.chatId = req.chatId;
            chatMapAction.type = ChatMapActionType.CREATE;
            chatMapAction.manager = req.fromId;
            chatMapAction.timestamp = core.stdc.time.time(null);
            foreach(message.MsgDefine.User u ; users)
            {
                chatMapAction.member ~= u.id;
            }

            // 向 msgserver 同步 chatId 对应 user 列表
            logInfo("Sync users of chatId (%d) to MsgServer");
            msgClient = MsgServerClient.getInstance().getForwardClient(to!int(req.chatId));
            msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
        }
    }

    static bool agree(FriendApply firendApply)
    {
        TransportSession msgClient = null;

        message.MsgDefine.User[] users = ApplyService.getUsers([firendApply.userId.to!string, firendApply.friendId.to!string], firendApply.userId.to!string);
        auto addFriend = new AddContact;

        string chatId = firendApply.id.to!string;
        string fromId = firendApply.userId.to!string;
        string toId = firendApply.friendId.to!string;

        addFriend.chatId = chatId;
        if (users !is null || users.length == 2)
        {
            if(!ApplyService.putFriend(chatId, fromId, toId, firendApply.src)) //已经是好友了
            {
                logError("already friend!!!");
                // return;
            }

            /**
                向好友双方发送回调消息
            **/
            msgClient = MsgServerClient.getInstance().getForwardClient(to!int(users[1].id));
            addFriend.user = users[0];
            addFriend.toId = users[1].id;
            logInfof("addFriend.user[0] = %s", users[0].id);
            logInfof("addFriend.user[1] = %s", users[1].id);
            msgClient.send(new MessageBuffer(MESSAGE.CMD_DEAL_FRIEND_RES, addFriend.toProtobuf.array));

            msgClient = MsgServerClient.getInstance().getForwardClient(to!int(users[0].id));
            addFriend.user = users[1];
            addFriend.toId = users[0].id;
            msgClient.send(new MessageBuffer(MESSAGE.CMD_DEAL_FRIEND_RES, addFriend.toProtobuf.array));
        }

        ChatMapAction chatMapAction = new ChatMapAction;
        chatMapAction.chatId = chatId;
        chatMapAction.type = ChatMapActionType.CREATE;
        chatMapAction.manager = firendApply.userId.to!string;
        chatMapAction.timestamp = core.stdc.time.time(null);
        foreach(u ; users)
        {
            chatMapAction.member ~= u.id;
        }
        msgClient = MsgServerClient.getInstance().getForwardClient(to!int(chatId));
        // 向msgserver发送chatId对应user列表
        msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
        
        return true;
    }

    //static void putApplyContactReq(string fromId,string toId, string message , int src, ref string chatId)
    //{
    //  auto friendRepo = new FriendApplyRepository();
    //  FriendApply obj = new FriendApply;
    //  obj.userId = to!int(fromId);
    //  obj.friendId = to!int(toId);
    //  obj.status = 0;
    //  obj.message = message;
    //  obj.created = core.stdc.time.time(null);
    //  obj.src = src;
    //  if (friendRepo.isApplyed(obj))
    //  {
    //    int id = friendRepo.putApplyContactReq(obj);
    //    logInfof("-------------id: %d",id);
    //    chatId = to!string(id);
    //  }
    //}

    static void updateApplyContactReq(string chatId, int succeeded)
    {
        auto friendRepo = new FriendApplyRepository();
        friendRepo.update(chatId, succeeded);
    }

    static message.MsgDefine.User[] getUsers(string[] uids,string userId)
    {
        import model;
        UserRepository userRepo = new UserRepository;
        User[] users = userRepo.findAllByUIDs(uids);

        if (uids.length != users.length)
        {
            logError("user is not found");
            return null;
        }
        message.MsgDefine.User[] sortUsers;
        foreach(string u ; uids)
        {
            int i = 0;
            for(; i < users.length ; i++)
            {
                if (users[i].id == to!int(u))
                {
                break;
                }
            }
            sortUsers ~= toUser(users[i]);
        }

        auto friendRep = new FriendRepository;
        foreach(message.MsgDefine.User u; sortUsers)
        {
            auto f = friendRep.findByUid(to!int(userId), to!int(u.id));
            if (f !is null)
            {
                u.chatId = to!string(f.chatId);
                u.aliasName = f.aliasName;
            }
        }
        return sortUsers;
    }

    static bool putFriend(string chatId, string userId,string friendId, int src)
    {
        auto friendRep  = new FriendRepository;
        Friend a = friendRep.findByUid(to!int(friendId),to!int(userId));
        Friend b = friendRep.findByUid(to!int(userId),to!int(friendId));

        if (a !is null && b !is null)
        {
            return false;
        }

        if( a is null)
        {
            friendRep.putSingle(friendId,userId,chatId,src);
        }

        if( b is null)
        {
            friendRep.putSingle(userId,friendId,chatId,src);
        }
        return true;
        //else
        //{
            //friendRep.putFriend(userId,friendId,chatId,src);
        //  return true;
        //}
    }
}
